package com.dhq.myapp.util

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.ParcelUuid
import android.util.Log
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresPermission
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.MutableLiveData
import java.util.concurrent.ConcurrentHashMap

/**
 * DESC
 * Created by DHQ on 2025/10/11.
 */
class BluetoothHelper(
    val context: AppCompatActivity,
    val initStatus: (INIT_STATUS) -> Unit,
    val deviceFound: () -> Unit
) {
    companion object {
        const val TAG = "BluetoothHelper"
        //根据这个值过滤蓝牙设备
        const val GLASS_SEVICE_UUID = "00009100-0000-1000-8000-00805f9b34fb"

        // Request Code
        const val REQUEST_CODE_PERMISSIONS = 100

        // Required Permissions
        private val REQUIRED_PERMISSIONS = mutableListOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.BLUETOOTH,
            Manifest.permission.BLUETOOTH_ADMIN,
        ).apply {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                add(Manifest.permission.BLUETOOTH_SCAN)
                add(Manifest.permission.BLUETOOTH_CONNECT)
            }
        }.toTypedArray()

        // Init Status
        enum class INIT_STATUS {
            NotStart, INITING, INIT_END
        }
    }

    // Scan Results
    val scanResultMap: ConcurrentHashMap<String, BluetoothDevice> = ConcurrentHashMap()

    // Bonded Devices
    val bondedDeviceMap: ConcurrentHashMap<String, BluetoothDevice> = ConcurrentHashMap()

    var mListener: BluetoothListener?=null;

    // Scanner
    private val scanner by lazy {
        adapter?.bluetoothLeScanner ?: run {
            Toast.makeText(context, "不支持蓝牙", Toast.LENGTH_SHORT).show()
            showRequestPermissionDialog()
            throw Exception("不支持蓝牙!!")
        }
    }

    // Bluetooth Enabled
    @SuppressLint("MissingPermission")
    private val bluetoothEnabled: MutableLiveData<Boolean> = MutableLiveData<Boolean>().apply {
        this.observe(context) {
            if (this.value == true) {
                initStatus.invoke(INIT_STATUS.INIT_END)
                startScan()
            } else {
                showRequestBluetoothEnableDialog()
            }
        }
    }

    //  Bluetooth State Listener
    private val requestBluetoothEnable = context.registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            adapter = manager?.adapter
        } else {
            showRequestBluetoothEnableDialog()
        }
    }

    // Bluetooth Adapter
    private var adapter: BluetoothAdapter? = null
        set(value) {
            field = value
            value?.let {
                if (!it.isEnabled) {
                    //to Enable it
                    requestBluetoothEnable.launch(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
                } else {
                    bluetoothEnabled.postValue(true)
                }
            }
        }

    // Bluetooth Manager
    private var manager: BluetoothManager? = null
        set(value) {
            field = value
            initStatus.invoke(INIT_STATUS.INITING)
            value?.let {
                adapter = it.adapter
            } ?: run {
                Toast.makeText(context, "不支持蓝牙22", Toast.LENGTH_SHORT).show()
                showRequestPermissionDialog()
            }
        }

    // Permission Result
    val permissionResult: MutableLiveData<Boolean> = MutableLiveData<Boolean>().apply {
        this.observe(context) {
            if (it == true) {
                manager =
//                    context.getSystemService(AppCompatActivity.BLUETOOTH_SERVICE) as BluetoothManager
                context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
            } else {
                showRequestPermissionDialog()
            }
        }
    }

    interface BluetoothListener{
        fun deviceFound(device:BluetoothDevice)
    }



    fun setScanListener(listener:BluetoothListener){
        mListener=listener;
    }

    // Scan Listener
    val scanListener = object : ScanCallback() {
        @SuppressLint("MissingPermission")
        override fun onScanResult(callbackType: Int, result: ScanResult?) {
            super.onScanResult(callbackType, result)
            result?.let { r ->
                r.device.name?.let {
                    scanResultMap[it] = r.device
                    deviceFound.invoke()

                    Log.e("发现设备",r.device.name)

                    if (mListener!=null){
                        mListener?.deviceFound(r.device);
                    }
                }
            }
        }

        override fun onScanFailed(errorCode: Int) {
            super.onScanFailed(errorCode)

            Log.e(TAG, errorCode.toString())
//            Toast.makeText(
//                context, "扫描失败 $errorCode", Toast.LENGTH_SHORT
//            ).show()
        }
    }

    // check permissions
    fun checkPermissions() {
//        initStatus.invoke(INIT_STATUS.NotStart)
//        context.requestPermissions(REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        context.registerReceiver(
            bluetoothStateListener, IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)
        )
    }

    // Release
    @SuppressLint("MissingPermission")
    fun release() {
        context.unregisterReceiver(bluetoothStateListener)
        stopScan()
        permissionResult.postValue(false)
        bluetoothEnabled.postValue(false)
    }


    // Show Request Permission Dialog
    private fun showRequestPermissionDialog() {
        AlertDialog.Builder(context).setTitle("Permission").setMessage("请授予权限")
            .setPositiveButton("确定") { _, _ ->
                context.requestPermissions(
                    REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS
                )
            }.setNegativeButton("取消") { _, _ ->
//                Toast.makeText(
//                    context,
//                    "Permission does not granted, FINISH",
//                    Toast.LENGTH_SHORT
//                ).show()
                context.finish()
            }.show()
    }

    // Show Request Bluetooth Enable Dialog
    private fun showRequestBluetoothEnableDialog() {
        AlertDialog.Builder(context).setTitle("蓝牙").setMessage("请开启蓝牙")
            .setPositiveButton("确定") { _, _ ->
                requestBluetoothEnable.launch(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
            }.setNegativeButton("取消") { _, _ ->
//                Toast.makeText(
//                    context,
//                    "Bluetooth does not enabled, FINISH",
//                    Toast.LENGTH_SHORT
//                ).show()
                context.finish()
            }.show()
    }


    // Start Scan
    @SuppressLint("MissingPermission")
//    @RequiresPermission(Manifest.permission.BLUETOOTH_SCAN)
    fun startScan() {
        scanResultMap.clear()
        val connectedList = getConnectedDevices()
        for (device in connectedList) {
            device.name?.let {
                if (it.contains("Glasses", false)) {
                    bondedDeviceMap[it] = device
                    deviceFound.invoke()
                    Log.e("发现设备1",device.name)

                    if (mListener!=null){
//                        mListener?.deviceFound(device);
                    }
                }
            }
        }

        adapter?.bondedDevices?.forEach { d ->
            d.name?.let {
                if (it.contains("Glasses", false)) {
                    if (bondedDeviceMap[it] == null) {
                        bondedDeviceMap[it] = d
                    }
                }
                deviceFound.invoke()
                Log.e("发现设备2",d.name)

                if (mListener!=null){
//                    mListener?.deviceFound(d);
                }
            }
        }

        try {
            scanner.startScan(
                listOf<ScanFilter>(
                    ScanFilter.Builder()
//                        .setServiceUuid(ParcelUuid.fromString(GLASS_SEVICE_UUID))//Rokid Glasses Service
                        .build()
                ), ScanSettings.Builder().build(), scanListener
            )
        } catch (e: Exception) {

            Log.e(TAG, e.message.toString())

//            Toast.makeText(context, "扫描失败 ${e.message}", Toast.LENGTH_SHORT).show()
        }
    }

    // Stop Scan
//    @RequiresPermission(Manifest.permission.BLUETOOTH_SCAN)
    @SuppressLint("MissingPermission")
    fun stopScan() {
        scanner.stopScan(scanListener)
    }

    //  Get Connected Devices
    @SuppressLint("MissingPermission")
    private fun getConnectedDevices(): List<BluetoothDevice> {
        return adapter?.bondedDevices?.filter { device ->
            try {
                val isConnected =
                    device::class.java.getMethod("isConnected").invoke(device) as Boolean
                isConnected
            } catch (_: Exception) {
//                Toast.makeText(context, "获取设备失败", Toast.LENGTH_SHORT).show()
                false
            }
        } ?: emptyList()
    }

    // Bluetooth State Listener
    val bluetoothStateListener = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val action = intent?.action
            if (action == BluetoothAdapter.ACTION_STATE_CHANGED) {
                val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)
                when (state) {
                    BluetoothAdapter.STATE_OFF -> {
                        initStatus.invoke(INIT_STATUS.NotStart)
                        bluetoothEnabled.postValue(false)
                    }
                }
            }
        }
    }

}